/*
 * $Id: QEADIFFile.m 76 2009-06-23 16:11:53Z jon@bway.net $
 * Chalk
 *
 * Created 6/5/09
 * Copyright Jon Gordon
 * 
 * Permission is hereby granted, free of charge, to any person obtaining 
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including 
 * without limitation the rights to use, copy, modify, merge, publish, 
 * distribute, sublicense, and/or sell copies of the Software, and to 
 * permit persons to whom the Software is furnished to do so, subject to 
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#import "QEADIFFile.h"

#import "QEADIFInternal.h"

#import "QEADIFDataField.h"
#import "QEADIFElement.h"
#import "QEADIFParser.h"
#import "QEADIFValue.h"


#define ARRL_LOTW_LOG_SIG_TEXT @"ARRL Logbook of the World"

static NSArray *sortDescriptors;


@implementation QEADIFFile

@synthesize filename, createDate, modifyDate, adifHeaders, adifRecords, adifErrors;

#pragma mark LIFECYCLE METHODS
+ (void)initialize
{
    static BOOL initialized = NO;
    if (!initialized) {
        initialized = YES;
        //-NSLog(@"  initializing");
        NSSortDescriptor *nameDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"fieldName"
                                                                        ascending:YES] autorelease];
        sortDescriptors = [[NSArray arrayWithObject:nameDescriptor] retain];
    } // if
} // initialize

- (id)init
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    self = [super init];
    if (nil != self) {
        [self setFilename:nil];
        [self setCreateDate:nil];
        [self setModifyDate:nil];
        [self setAdifHeaders:nil];
        [self setAdifRecords:nil];
        [self setAdifErrors:nil];
    } // if
    
    return self;
} // init

- (void)dealloc
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    [self setFilename:nil];
    [self setCreateDate:nil];
    [self setModifyDate:nil];
    [self setAdifHeaders:nil];
    [self setAdifRecords:nil];
    [self setAdifErrors:nil];
    
    [super dealloc];
} // dealloc


- (void)regenerateHeadersWithApplicationName:(NSString *)name
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    
    QEADIFValue *programIDValue = [QEADIFValue stringFromString:name];
    QEADIFDataField *programIDField = [[QEADIFDataField alloc] initWithFieldName:@"PROGRAMID"
                                                                      fieldValue:programIDValue];
    [self setAdifHeaders:[NSArray arrayWithObject:[programIDField autorelease]]];
} // regenerateHeadersWithApplicationName:


+ (NSString *)adifRecordAsText:(NSArray *)record
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    
    NSMutableString *result = [[NSMutableString alloc] init];
    
    for (QEADIFDataField *field in record) {
        if ((qeADIFDataTypeUnspecified == [field typeCode]) ||
            (qeADIFDataTypeEnumeration == [field typeCode])) {
            [result appendFormat:@"<%@:%lu>%@\n",
             [field fieldName],
             ((unsigned long) [[[field fieldValue] stringValue] length]),
             [[field fieldValue] stringValue]];
        } else {
            [result appendFormat:@"<%@:%lu:%C>%@\n",
             [field fieldName],
             ((unsigned long) [[[field fieldValue] stringValue] length]),
             [field typeCode],
             [[field fieldValue] stringValue]];
        } // else        
    } // for
    
    return [NSString stringWithString:[result autorelease]];
} // adifRecordAsText:


- (BOOL)writeToFile:(NSString *)path error:(NSError **)error
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    return [[self exportAsADIFText] writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:error];
} // writeToFile:error:


- (NSString *)allRecordsAsTextWithCount:(BOOL)includeCount
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    NSMutableString *result = [[NSMutableString alloc] init];
    
    int i = 0;
    for (NSArray *record in adifRecords) {
        NSArray *sortedRecord = [record sortedArrayUsingDescriptors:sortDescriptors];
        if (includeCount) {
            [result appendFormat:@"record %d:\n", ++i];
        } // if
        [result appendFormat:@"%@<eor>\n\n", 
         [QEADIFFile adifRecordAsText:sortedRecord]];
    } // for
    
    return [NSString stringWithString:[result autorelease]];
} // allRecordsAsText


- (NSString *)exportAsADIFText
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    NSMutableString *result = [[NSMutableString alloc] initWithString:@"ADIF Data Export\n\n"];
    if (0 < [adifHeaders count]) {
        [result appendFormat:@"%@\n<eoh>\n\n",
         [QEADIFFile adifRecordAsText:adifHeaders]];
    } // if
    
    [result appendString:[self allRecordsAsTextWithCount:NO]];
    
    return [NSString stringWithString:[result autorelease]];
} // exportAsADIFText

- (NSString *)dump
{
    NSMutableString *result = [[NSMutableString alloc] initWithString:@"\n +++ DUMP OF QEADIFFILE CONTENTS +++\n\n"];
    
    if (nil == [self filename]) {
        [result appendString:@"filename: (nil)\n"];
    } else {
        [result appendFormat:@"filename: \'%@\'\n", [self filename]];
    } // else
    
    if (nil == [self createDate]) {
        [result appendString:@"creation date: (nil)\n"];
    } else {
        [result appendFormat:@"creation date: %@\n", [self createDate]];
    } // else
    
    if (nil == [self modifyDate]) {
        [result appendString:@"modification date: (nil)\n\nHEADERS:\n"];
    } else {
        [result appendFormat:@"modification date: \'%@\'\n\nHEADERS:\n", [self modifyDate]];
    } // else
    
    if (0 == [[self adifHeaders] count]) {
        [result appendString:@"--- NONE ---\n\nRECORDS:\n"];
    } else {
        [result appendFormat:@"%@\n<eoh>\n\nRECORDS:\n",
         [QEADIFFile adifRecordAsText:[self adifHeaders]]];
    } // if
    
    if (0 == [[self adifRecords] count]) {
        [result appendString:@"--- NONE ---\n\nERRORS:\n"];
    } else {
        [result appendFormat:@"%@\n<eoh>\n\nERRORS:\n",
         [self allRecordsAsTextWithCount:NO]];
    } // if
    
    if (0 == [[self adifErrors] count]) {
        [result appendString:@"--- NONE ---\n\n+++ END OF DUMP +++\n\n"];
    } else {
        for (QEADIFElement *errorElement in [self adifErrors]) {
            [result appendFormat:@"%@\n",
             [[[errorElement error] userInfo] objectForKey:NSLocalizedDescriptionKey]];
        } // for
        [result appendString:@"\n\n+++ END OF DUMP +++\n\n"];
    } // if
    return [NSString stringWithString:[result autorelease]];
} // dump
@end
